﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace NDF.XnaLibrary.Models
{
	public class SkinnedModelInfo
	{
		/// <summary>
		/// Constructs a new skinned model info object.
		/// </summary>
		public SkinnedModelInfo(List<Matrix> bindPose, List<Matrix> inverseBindPose,
							List<int> skeletonHierarchy, Dictionary<string, int> boneIndices)
		{
			BindPose = bindPose;
			InverseBindPose = inverseBindPose;
			SkeletonHierarchy = skeletonHierarchy;
			BoneNameIndices = boneIndices;

			InitDefaultSkeletonIndices();
		}


		/// <summary>
		/// Private constructor for use by the XNB deserializer.
		/// </summary>
		private SkinnedModelInfo()
		{
		}

		/// <summary>
		/// Bindpose matrices for each bone in the skeleton,
		/// relative to the parent bone.
		/// </summary>
		[ContentSerializer]
		public List<Matrix> BindPose { get; private set; }


		/// <summary>
		/// Vertex to bonespace transforms for each bone in the skeleton.
		/// </summary>
		[ContentSerializer]
		public List<Matrix> InverseBindPose { get; private set; }


		/// <summary>
		/// For each bone in the skeleton, stores the index of the parent bone.
		/// </summary>
		[ContentSerializer]
		public List<int> SkeletonHierarchy { get; private set; }


		/// <summary>
		/// Dictionary mapping bone names to their indices in the preceding lists.
		/// </summary>
		[ContentSerializer]
		public Dictionary<string, int> BoneNameIndices { get; private set; }

		/// <summary>
		/// Dictionary mapping bone ModelBoneIndexes to their indices in the preceding list.
		/// Animation is based on this property, so make sure everything`s set as it should be.
		/// </summary>
		[ContentSerializer]
		public Dictionary<ModelBoneIndex, int> SkeletonIndices { get; set; }

		private void InitDefaultSkeletonIndices()
		{
			SkeletonIndices = new Dictionary<ModelBoneIndex,int>();
			foreach (string boneName in BoneNameIndices.Keys)
			{
				foreach (string boneIndex in Enum.GetNames(typeof(ModelBoneIndex)))
				{
					if (boneName.ToLowerInvariant() == boneIndex.ToLowerInvariant())
					{
						ModelBoneIndex bone = (ModelBoneIndex)Enum.Parse(typeof(ModelBoneIndex), boneIndex);
						SkeletonIndices.Add(bone, BoneNameIndices[boneName]);
					}
				}
			}
		}
	}
}
